package com.topisv.tms.rest.qimen.qmservice;

import java.io.StringReader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.xml.bind.JAXB;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.EdiOrder;
import com.topisv.tms.entity.stock.instorage.pre.InstorageBillPre;
import com.topisv.tms.entity.ulorder.Ulorder;
import com.topisv.tms.exception.ErrorCode;
import com.topisv.tms.exception.PaiUException;
import com.topisv.tms.repository.EdiOrderDao;
import com.topisv.tms.repository.qimen.DeliveryOrderTaskDao;
import com.topisv.tms.repository.ulorder.UlorderDao;
import com.topisv.tms.rest.qimen.qmentity.request.allcancel.AllCancel;
import com.topisv.tms.rest.qimen.qmentity.response.QMReponse;
import com.topisv.tms.rest.qimen.qmenum.AllCancelCode;
import com.topisv.tms.rest.qimen.qmsend.QmRequestSender;
import com.topisv.tms.rest.qimen.request.RequestParams;
import com.topisv.tms.rest.qimen.response.ResponseParams;
import com.topisv.tms.rest.qimen.util.validator.ValidatorUtil;
import com.topisv.tms.service.stock.preinstorage.PreInstorageService;
import com.topisv.tms.service.ulorder.UlorderService;
import com.topisv.tms.service.work.WorkOrderService;
import com.topisv.tms.utils.WmsContants;
import com.topisv.tms.utils.enums.TaskStatus;

/**
 * 单据取消接口 create by gaohuan 2015-05-09
 * */
@Component
@Lazy(false)
@Transactional(readOnly =  false)
public class AllCancelService   {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private EdiOrderDao ediOrderDao;
	@Autowired
	private WorkOrderService workOrderService;
	@Autowired
	private UlorderService ulorderService;
	@Autowired
	private PreInstorageService preInstorageService;
	@Autowired
	private UlorderDao ulorderDao;
	@Resource(type=DeliveryProcessService.class)
	private QmRequestSender<Map<String,Object>> deliveryProcessService;
	
	@Autowired
	private DeliveryOrderTaskDao deliveryOrderTaskDao;
	
	private EdiOrder cancelOrder;
	
	
	@Transactional(readOnly = false,rollbackFor=Exception.class,propagation=Propagation.REQUIRED)
	public ResponseParams execute(RequestParams params)throws PaiUException{
		cancelOrder = null;
		ResponseParams responseParams = new ResponseParams();
		String xmlString = params.getRequestXml();
		String responseXml = "";
		String customerOrdeno = "";
		String customerCode = "";
		
		if(xmlString==null){}
		QMReponse re = new QMReponse(); 
		try{
			logger.info("--------取消单开始解析xml---------");
			AllCancel allCancel = JAXB.unmarshal(new StringReader(xmlString), AllCancel.class);
			
			// 报文校验
            String reqValidatorMsg = ValidatorUtil.qmXmlValidator(allCancel);
            if (!ValidatorUtil.SUCCESS_CODE.equals(reqValidatorMsg)) {
                ResponseParams response = new ResponseParams();
                response.setResponseXml(reqValidatorMsg.toString());
                return response;
            }
			
			if(allCancel==null){
				re = new QMReponse(); 
				re.setFlag("failure");
				re.setCode("QMERR001");
				re.setMessage("系统异常!");
				logger.info("--------取消单失败---------");
			}else {
					logger.info("--------取消单解析xml完成---------"+allCancel.getOrderCode()+"|"+allCancel.getOrderId()+"|"+allCancel.getOrderType()+"|");
					customerOrdeno = allCancel.getOrderCode();
					customerCode = allCancel.getOwnerCode();
					EdiOrder ediOrder = getEdiOrder(allCancel);
					Ulorder ulorder = ulorderDao.getCustomerOrdeno(customerCode,customerOrdeno);
					
					// begin add 20161025 取消订单时，订单可能还未被处理，此时只能从报文中拦截
					Long deliveryOrderTaskId = null;
					if (ediOrder == null && ulorder == null) {
					    
                        if (AllCancelCode.JYCK.getCode().equals(allCancel.getOrderType())
                            || AllCancelCode.HHCK.getCode().equals(allCancel.getOrderType())
                            || AllCancelCode.BFCK.getCode().equals(allCancel.getOrderType())
                            || AllCancelCode.PTCK.getCode().equals(allCancel.getOrderType())
                            || AllCancelCode.DBCK.getCode().equals(allCancel.getOrderType())
                            || AllCancelCode.QTCK.getCode().equals(allCancel.getOrderType())) {
					        
    					    List<Map<String, Object>> taskList = deliveryOrderTaskDao.findByCustomerOrderNo(customerCode, customerOrdeno);
    					    for (Map<String, Object> t : taskList) {
    					        String status = (String) t.get("dealStatus");
    					        if ("0".equals(status) || "1".equals(status) || "2".equals(status) || "3".equals(status)) {
    					            deliveryOrderTaskId = Long.valueOf(String.valueOf(t.get("id")));
    					            break;
    					        }
    					    }
    					    
    					    logger.info("取消订单接口，订单为空，从报文中取到的报文ID:{}，客户订单号:{}", deliveryOrderTaskId, customerOrdeno);
					    }
					}
					
					if (deliveryOrderTaskId != null) {
					    int cnt = deliveryOrderTaskDao.cancel(deliveryOrderTaskId, TaskStatus.CANCEL.getStatus());
					    
					    if (cnt == 0) { //此时未找到符合条件的报文，可能是已被处理，需再次重新查找EdiOrder，确保不会遗漏订单
					        ediOrder = getEdiOrder(allCancel);
					        logger.info("取消订单接口，查找到的报文id:{}已处理，重新获取EdiOrder.id:{}，客户订单号:{}", deliveryOrderTaskId, ediOrder == null ? "null" : ediOrder.getId(), customerOrdeno);
					    } else {
					        logger.info("取消订单接口，已拦截报文id:{}，并更新dealStatus为6，客户订单号:{}", deliveryOrderTaskId, customerOrdeno);
					        
					        re = new QMReponse(); 
			                re.setFlag("success");
			                re.setCode("QMINFO001");
			                re.setMessage("取消成功");
					    }
					}
					// end add 20161025 取消订单时，订单可能还未被处理，此时只能从报文中拦截
					
					if (null != ediOrder || null != ulorder) {
						if (null == ulorder) {
							if(AllCancelCode.JYCK.getCode().equals(allCancel.getOrderType())||
									AllCancelCode.HHCK.getCode().equals(allCancel.getOrderType())||
									AllCancelCode.BFCK.getCode().equals(allCancel.getOrderType())||
									AllCancelCode.PTCK.getCode().equals(allCancel.getOrderType())||
									AllCancelCode.DBCK.getCode().equals(allCancel.getOrderType())||
									AllCancelCode.QTCK.getCode().equals(allCancel.getOrderType())
									) {
										logger.info("---------Cancel online orders begin------");
										re = salesOutBoundCancel(ediOrder,allCancel);
										logger.info("---------Cancel online orders end---------");
									}
						} else {
							if(AllCancelCode.CGTH.getCode().equals(allCancel.getOrderType())
									|| AllCancelCode.B2BCK.getCode().equals(allCancel.getOrderType())
									|| AllCancelCode.PTCK.getCode().equals(allCancel.getOrderType())
									|| AllCancelCode.DBCK.getCode().equals(allCancel.getOrderType())
									|| AllCancelCode.QTCK.getCode().equals(allCancel.getOrderType()))
							{
								logger.info("---------Cancel line orders begin------");
								ulorderService.cancelBill(customerOrdeno);
								re = new QMReponse(); 
								re.setFlag("success");
								re.setCode("QMINFO001");
								re.setMessage("取消成功");
								logger.info("---------Cancel line orders end---------");
							}
						}
					}else if(AllCancelCode.CGRK.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.DBRK.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.QTRK.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.XTRK.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.HHRK.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.CNJG.getCode().equals(allCancel.getOrderType())||
							AllCancelCode.THRK.getCode().equals(allCancel.getOrderType())
							) {
						logger.info("--------入库单取消开始---------");
						re = instorageBillCancel(allCancel);
						logger.info("--------入库单取消结束---------");
					}
				}
		
		}catch(PaiUException e){
			re = new QMReponse(); 
			re.setFlag("failure");
			re.setCode("QMERR001");
			re.setMessage(e.getErrorCode());
			logger.error("error info:",e);
			throw new PaiUException(ErrorCode.DATA_ERROR);
		}catch(Exception e){
			re = new QMReponse(); 
			re.setFlag("failure");
			re.setCode("QMERR001");
			re.setMessage("系统异常!");
			logger.error("error info:",e);
			e.printStackTrace();
			throw new PaiUException(ErrorCode.DATA_ERROR);
		}
		StringWriter writer = new StringWriter();
		JAXB.marshal(re,writer);
		responseXml = writer.toString();
		// 设置返回报文信息
		responseParams.setResponseXml(responseXml);
		return responseParams;
	}
	
	@Transactional(readOnly = false,rollbackFor=Exception.class,propagation=Propagation.REQUIRED)
	public void executeBefore()throws PaiUException{
		EdiOrder ediOrder = cancelOrder;
		String orderno = ediOrder==null?"null" : ediOrder.getOrdeno();
		try{
			this.logger.info("------调用奇门出库单流水 (取消) orderno："+orderno+"---start------");
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("ediOrder", ediOrder);
			params.put("status", "cancel");
			
			deliveryProcessService.send(params,ediOrder.getCustomerCode());
			this.logger.info("------调用奇门出库单流水 (取消) orderno："+orderno+"---end------");
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	
	/**
	 * 取消线上订单
	 * 
	 * @param ediOrder
	 * @param allCancel
	 * @return
	 * @throws Exception
	 */
	public QMReponse salesOutBoundCancel(EdiOrder ediOrder ,AllCancel allCancel) throws Exception {
		QMReponse re = null;
		
		// 获取取消订单信息
		if(null != ediOrder){
			
			String msg=this.workOrderService.cancelOrder(ediOrder.getOrdeno(),WmsContants.SYSTEM_ADMIN,false);
			if("success".equals(msg)){
				re = new QMReponse(); 
				re.setFlag("success");
				re.setCode("QMINFO001");
				re.setMessage("取消成功");
				cancelOrder = ediOrder;
			}else {
				re = new QMReponse(); 
				re.setFlag("failure");
				if("noexist".equals(msg)){//不存在
					re.setCode("QMERR_SOC_001");
					re.setMessage("不能取消，请稍后再试");
				}else if("cancel".equals(msg)){//已经取消
					re.setCode("QMERR_SOC_002");
					re.setMessage("该单已经取消");
				}
//				else if("sended".equals(msg)){
//					re.setCode("QMERR_SOC_003");//已经发货
//					re.setMessage("该单已经发货");
//				}
				else if("package".equals(msg)){//@张卫泽修改的
					re.setCode("QMERR_SOC_003");//已经包装
					re.setMessage("该单已经包装");
				}
				else {
					re.setCode("QMERR001");
					re.setMessage("取消失败");
				}
			}
		}else {
			//不存在
			re = new QMReponse(); 
			re.setFlag("failure");
			re.setCode("QMERR_SOC_001");
			re.setMessage("取消单不存在!");
			logger.info("orderCode:"+allCancel.getOrderCode()+" orderId:"+allCancel.getOrderId()+" 取消单不存在!");
		}
		return re;
		
	}
	
	/**
	 * 取消入库单
	 * 
	 * @param allCancel
	 * @return
	 * @throws Exception
	 */
	public QMReponse instorageBillCancel(AllCancel allCancel) throws Exception {
		QMReponse re = null;
		String customerOrderNo = allCancel.getOrderCode();		//客户单号
		String billCode = allCancel.getOrderId();			//预约单号
		
		InstorageBillPre ibPre = preInstorageService.findByBillCode(billCode);
		if(ibPre == null) {
			re = new QMReponse(); 
			re.setFlag("failure");
			re.setCode("QMERR_IBC_001");
			re.setMessage("取消单不存在!");
		}else if(!ibPre.getCustomerOrderNo().equals(customerOrderNo)){
			re = new QMReponse(); 
			re.setFlag("failure");
			re.setCode("QMERR_IBC_002");
			re.setMessage("OrderCode 与 系统中OrderCode不一致!");
		}else {
			preInstorageService.cancelPreOrderByCusNo(ibPre.getCustomerOrderNo(), ibPre.getCustomerCode());
			re = new QMReponse(); 
			re.setFlag("success");
			re.setCode("QMINFO001");
			re.setMessage("取消成功");
		}
		return re;
	}

	
	public List<EdiOrder> getEidOrder(EdiOrder soq) {
		final String customerCode = soq.getCustomerCode();
		// delete by yuansheng 分仓
		// final String warehouseCode = soq.getWarehouseCode();
		// delete by yuansheng 分仓
		final String customerOrdeno = soq.getCustomerOrdeno();
		final String orderno = soq.getOrdeno();
		
		logger.info("--------查询ediOrder---------customerOrdeno:"+customerOrdeno+" orderno:"+orderno);
		List<EdiOrder> ediOrderList = ediOrderDao.findAll(new Specification<EdiOrder>(){
			@Override
			public Predicate toPredicate(Root<EdiOrder> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
				Predicate pre = cb.conjunction();
				
				if(StringUtils.isNotBlank(customerOrdeno)){
					pre.getExpressions().add(cb.equal(r.<String>get("customerOrdeno"), customerOrdeno));
				}
				
				/*if(StringUtils.isNotBlank(orderno)){
					pre.getExpressions().add(cb.equal(r.<String>get("ordeno"), orderno));
				}*/
				//pre.getExpressions().add(cb.equal(r.<String>get("status"), "pending"));
				pre.getExpressions().add(cb.equal(r.<String>get("orderStatus"), "ok"));
				if(StringUtils.isNotBlank(customerCode)){
					pre.getExpressions().add(cb.equal(r.<String>get("customerCode"), customerCode));
				}
				
				// delete by yuansheng 分仓
//				if(StringUtils.isNotBlank(warehouseCode)){
//					pre.getExpressions().add(cb.equal(r.<String>get("warehouseCode"), warehouseCode));
//				}
				// delete by yuansheng 分仓
				return pre;
			}
			
		});
		return ediOrderList;
	}

	
	
	/**
	 * 获取取消线上订单数据
	 * 
	 * @return List<EdiOrder> [返回类型说明]
	 * @exception throws [违例类型] [违例说明]
	 * @see [类、类#方法、类#成员]
	 */
	private EdiOrder getEdiOrder(AllCancel allCancel) {
		
		// 设置查询参数
		EdiOrder ediOrderParam = new EdiOrder();
		ediOrderParam.setOrdeno(allCancel.getOrderId());
		ediOrderParam.setCustomerOrdeno(allCancel.getOrderCode());
		ediOrderParam.setCustomerCode(allCancel.getOwnerCode());
		ediOrderParam.setWarehouseCode(allCancel.getWarehouseCode());
		List<EdiOrder> ediOrderList	 = getEidOrder(ediOrderParam);
		
		return null != ediOrderList && ediOrderList.size() > 0 ? ediOrderList.get(0) : null;
	}
	
}
